using Microsoft.Extensions.Logging;
using RawRestructure.Enums;
using RawRestructure.Models;
using RawRestructure.Services.Interfaces;
using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;

namespace RawRestructure.Services
{
    /// <summary>
    /// TCP客户端服务实现
    /// </summary>
    public class TcpClientService : ITcpClientService
    {
        private readonly ILogger<TcpClientService> _logger;
        private TcpClient? _tcpClient;
        private NetworkStream? _stream;
        private readonly SemaphoreSlim _sendLock = new SemaphoreSlim(1, 1);
        private bool _isConnected;
        
        /// <summary>
        /// 是否已连接
        /// </summary>
        public bool IsConnected
        {
            get => _isConnected;
            private set
            {
                if (_isConnected != value)
                {
                    _isConnected = value;
                    ConnectionStateChanged?.Invoke(this, value);
                }
            }
        }
        
        /// <summary>
        /// 连接状态变化事件
        /// </summary>
        public event EventHandler<bool>? ConnectionStateChanged;
        
        public TcpClientService(ILogger<TcpClientService> logger)
        {
            _logger = logger;
        }
        
        /// <summary>
        /// 异步连接到服务器
        /// </summary>
        /// <param name="ip">服务器IP</param>
        /// <param name="port">服务器端口</param>
        /// <returns>连接结果</returns>
        public async Task<bool> ConnectAsync(string ip, int port)
        {
            try
            {
                if (IsConnected)
                {
                    _logger.LogDebug("已连接到工作站，无需重复连接");
                    return true;
                }
                
                _logger.LogInformation("尝试连接工作站: {IP}:{Port}", ip, port);
                
                // 断开旧连接（如果有）
                await DisconnectAsync();
                
                // 创建新的TCP客户端
                _tcpClient = new TcpClient();
                
                // 设置连接超时
                var connectTask = _tcpClient.ConnectAsync(ip, port);
                var timeoutTask = Task.Delay(5000); // 5秒超时
                
                // 等待连接或超时
                var completedTask = await Task.WhenAny(connectTask, timeoutTask);
                
                if (completedTask == timeoutTask)
                {
                    _logger.LogWarning("连接工作站超时");
                    await DisconnectAsync();
                    return false;
                }
                
                // 检查连接是否成功
                if (!_tcpClient.Connected)
                {
                    _logger.LogWarning("无法连接到工作站");
                    await DisconnectAsync();
                    return false;
                }
                
                // 获取网络流
                _stream = _tcpClient.GetStream();
                
                IsConnected = true;
                _logger.LogInformation("已连接到工作站: {IP}:{Port}", ip, port);
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "连接工作站时发生错误");
                await DisconnectAsync();
                return false;
            }
        }
        
        /// <summary>
        /// 异步断开连接
        /// </summary>
        /// <returns>异步任务</returns>
        public async Task DisconnectAsync()
        {
            await _sendLock.WaitAsync();
            try
            {
                if (_stream != null)
                {
                    _stream.Close();
                    _stream = null;
                }
                
                if (_tcpClient != null)
                {
                    _tcpClient.Close();
                    _tcpClient = null;
                }
                
                IsConnected = false;
                _logger.LogInformation("已断开工作站连接");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "断开连接时发生错误");
            }
            finally
            {
                _sendLock.Release();
            }
        }
        
        /// <summary>
        /// 同步断开连接（用于应用关闭时）
        /// </summary>
        public void DisconnectSync()
        {
            try
            {
                if (_stream != null)
                {
                    _stream.Close();
                    _stream = null;
                }
                
                if (_tcpClient != null)
                {
                    _tcpClient.Close();
                    _tcpClient = null;
                }
                
                IsConnected = false;
                _logger.LogInformation("已同步断开工作站连接");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "同步断开连接时发生错误");
            }
        }
        
        /// <summary>
        /// 异步发送数据包
        /// </summary>
        /// <param name="packet">TCP数据包</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendPacketAsync(TcpPacket packet)
        {
            if (!IsConnected || _stream == null || _tcpClient == null)
            {
                _logger.LogWarning("未连接到工作站，无法发送数据");
                return false;
            }
            
            await _sendLock.WaitAsync();
            try
            {
                // 将数据包转换为字节数组
                byte[] data = packet.ToByteArray();
                
                // 发送数据
                await _stream.WriteAsync(data, 0, data.Length);
                
                _logger.LogDebug("发送数据包: {CommandType}, 长度: {Length}", packet.CommandType, data.Length);
                return true;
            }
            catch (IOException ex)
            {
                _logger.LogError(ex, "发送数据时发生IO错误，可能连接已断开");
                // 连接可能已断开，更新状态
                IsConnected = false;
                return false;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "发送数据时发生错误");
                return false;
            }
            finally
            {
                _sendLock.Release();
            }
        }
        
        /// <summary>
        /// 异步发送数据包
        /// </summary>
        /// <param name="commandType">命令类型</param>
        /// <param name="data">数据</param>
        /// <returns>发送结果</returns>
        public async Task<bool> SendPacketAsync(CommandType commandType, byte[] data)
        {
            var packet = TcpPacket.Create(commandType, data);
            return await SendPacketAsync(packet);
        }
    }
} 